Executor 框架

Java的线程既是工作单元,也是执行机制。从JDK5开始,把工作单元与执行机制分离开来。工作单元包括RunnableCallable,而执行机制由Executor框架提供。

Executor 框架简介

HotSpot VM的线程模型中,Java线程被一对一映射为本地操作系统线程。Java线程启动时会创建一个本地操作系统线程;当该Java线程终止时,这个操作系统线程也被收回。操作系统会调度所有线程并将他们分配给可用的CPU。如图

两级调度模型

Executor 框架结构

主要由3大部分组成:

  • 任务:包括被执行任务需要实现的接口:Runnable接口和Callable接口
  • 任务的执行:包括任务执行机制的核心接口Executor,以及继承自它的ExecutorService接口。有两个关键类实现了ExecutorService接口(ThreadPoolExecutorScheduledThreadPoolExecutor)。
  • 异步计算的结果:包括接口Future和实现它的FutureTask
Executor框架的成员
  • ThreadPoolExecutor:通常使用工具类Executors来创建。Executors可以创建3种类型的ThreadPoolExecutor:

    • SingleThreadExecutor:用于需要保证顺序地执行每个任务,并且在任意时间点不会有多个线程是活动的应用场景。下面是创建单个线程的API

      1
      2
      public static ExecutorService newSingleThreadExecutor();
      public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)
    • FixedThreadPool:用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器。下面是创建使用固定线程数的FixedThreadPool的API

      1
      2
      public static ExecutorService newFixedThreadPool(int nThreads);
      public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);
    • CachedThreadPool:它是无界大小的线程池,用于执行很多短期异步小任务的小程序,或者是负载比较轻的服务器。下面是创建一个根据需要创建新线程的API

      1
      2
      public static ExecutorService newCachedThreadPool();
      public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);
  • ScheduledThreadPoolExecutor:通常使用工具类Executors来创建。Executors可以创建2种类型的ScheduledThreadPoolExecutor:

    • ScheduledThreadPoolExecutor:包含若干个线程的ScheduledThreadPoolExecutor,适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的场景。下面是创建的API:

      1
      2
      3
      public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
      public static ScheduledExecutorService newScheduledThreadPool(
      int corePoolSize, ThreadFactory threadFactory);
    • SingleThreadScheduledExecutor:只包含一个线程的ScheduledThreadPoolExecutor,适用于需要单个线程执行周期任务,同时需要保证顺序地执行各个任务的场景。下面是创建的API:

      1
      2
      public static ScheduledExecutorService newSingleThreadScheduledExecutor();
      public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory);
  • Future接口
    Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。当我们把Runnable接口或Callable接口的实现类提交(submit)给ThreadPoolExecutorScheduledThreadPoolExecutor时,ThreadPoolExecutorScheduledThreadPoolExecutor会向我们返回一个FutureTask对象。下面是对应API:

    1
    2
    3
    public <T> Future<T> submit(Callable<T> task)
    public <T> Future<T> submit(Runnable task, T result)
    public Future<?> submit(Runnable task)
  • Runnable接口和Callable接口
    这两个接口的实现类都可以被ThreadPoolExecutorScheduledThreadPoolExecutor执行,最后一个方法没有返回值,其他均可以通过得到的FutureTask对象的get方法获取执行后结果。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class ExecutorTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(5);
    //submit(Runnable task)
    Future<String> f1 = executor.submit(new Runnable(){
    @Override
    public void run() {
    System.out.println(1);
    }
    },"result");
    System.out.println(f1.get());
    //submit(Runnable task,T result)
    Future f2 = executor.submit(new Runnable(){
    @Override
    public void run() {
    System.out.println(2);
    }
    });
    System.out.println(f2.get());
    //submit(Callable<T> task)
    Future<String> f3 = executor.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
    System.out.println(3);
    return "result";
    }
    });
    System.out.println(f3.get());
    }
    }

执行结果

1
2
3
4
5
6
1
result
2
null
3
result

除了自己实现Callable接口外,Executors可以把一个Runnable包装成一个Callable,下面是对应的API

1
2
public static Callable<Object> callable(Runnable task)
public static Callable<T> callable(Runnable task, T result)

此时将这种转换过的对象交给ThreadPoolExecutorScheduledThreadPoolExecutor执行时,第一个种转换方法不会有返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Callable c1 = Executors.callable(new Runnable() {
@Override
public void run() {
System.out.println(4);
}
});
Callable c2 = Executors.callable(new Runnable() {
@Override
public void run() {
System.out.println(5);
}
},"result2");
Future f4 = executor.submit(c1);
System.out.println(f4.get());
Future f5 = executor.submit(c2);
System.out.println(f5.get());

执行结果

1
2
3
4
4
null
5
result2

文章目录
  1. 1. Executor 框架简介
  2. 2. Executor 框架结构
  3. 3. Executor框架的成员
|